package com.iq50.client.controller;

import com.google.common.util.concurrent.SettableFuture;
import com.iq50.client.routeguide.*;
import com.iq50.client.service.RouteGuideService;
import io.grpc.stub.StreamObserver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

/**
 * @author: guozonghao
 * @create: 2023-12-06 19:59
 */
@RestController
public class RouteGuideController {
    @Autowired
    private RouteGuideService routeGuideService;

    @Autowired
    private RouteGuideClient routeGuideClient;

    @GetMapping("/GetFeature")
    public String GetFeature(){
        Point point = Point.newBuilder()
                        .setLatitude(120000)
                        .setLongitude(120000)
                        .build();
        Feature feature = routeGuideService.GetFeature(point);

        return feature.toString();
    }

    //服务器发送流式数据给客户端
    @GetMapping("/ListFeatures")
    public String ListFeatures(){
        Rectangle rectangle = Rectangle.newBuilder()
                .setHi(Point.newBuilder()
                        .setLatitude(400000000)
                        .setLongitude(-750000000)
                        .build())
                .setLo(Point.newBuilder()
                        .setLatitude(420000000)
                        .setLongitude(-730000000)
                        .build()).build();
        Iterator<Feature> featureIterator = routeGuideService.ListFeatures(rectangle);
        String res="";
        while (featureIterator.hasNext()){
            res += featureIterator.next().toString();
        }
        return res;
    }

    //客户端发送流式数据给服务器端
    @GetMapping("/recordRoute")
    public String recordRoute() {
        List<Feature> features = new ArrayList<Feature>();
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(1200000).setLongitude(12000).build()).setName("asd").build());
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(2200000).setLongitude(12000).build()).setName("asdf").build());
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(3200000).setLongitude(12000).build()).setName("ewfew").build());
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(4200000).setLongitude(12000).build()).setName("rtgr").build());
        features.add(Feature.newBuilder().setLocation(Point.newBuilder().setLatitude(5200000).setLongitude(12000).build()).setName("wer").build());
        int numPoints = features.size();
        //=========================
        //用来控制异步操作
        final SettableFuture<Void> finishFuture = SettableFuture.create();
        StreamObserver<RouteSummary> responseObserver = new StreamObserver<RouteSummary>() {
            @Override
            public void onNext(RouteSummary summary) {
                try {
                    System.out.printf("Finished trip with %d points. Passed %d features. Travelled %d meters. It took %d seconds.\n",
                            summary.getPointCount(), summary.getFeatureCount(), summary.getDistance(), summary.getElapsedTime());

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public void onError(Throwable t) {
                //表示操作已经出错，进行通知
                finishFuture.setException(t);
            }

            @Override
            public void onCompleted() {
                //表示操作已经完成
                finishFuture.set(null);
            }
        };
        //获得一个请求的观察者对象
        StreamObserver<Point> requestObserver = routeGuideClient.getRPCAsyncMethods().recordRoute(responseObserver);

        try {
            // 随机挑选节点发送给服务器
            StringBuilder numMsg = new StringBuilder();
            Random rand = new Random();
            for (int i = 0; i < numPoints; ++i) {
                int index = rand.nextInt(features.size());
                Point point = features.get(index).getLocation();
                System.out.printf("Visiting point %d, %d\n", point.getLatitude(),point.getLongitude());
                //将点发送给服务器
                requestObserver.onNext(point);
                // Sleep for a bit before sending the next one.
                Thread.sleep(rand.nextInt(1000) + 500);
                if (finishFuture.isDone()) {
                    break;
                }
            }
            System.out.println(numMsg.toString());
            //告诉服务器端客户端以及发送完全部信息
            requestObserver.onCompleted();
            //等待服务器端完成处理
            finishFuture.get();
            System.out.println("Finished RecordRoute\n");
        } catch (Exception e) {
            requestObserver.onError(e);
            System.out.printf("RecordRoute Failed\n", e);
        }

        return "调用成功";
    }

    @GetMapping("/routeChat")
    public String routeChat() {
        final SettableFuture<Void> finishFuture = SettableFuture.create();
        StreamObserver<RouteNote> requestObserver = routeGuideClient.getRPCAsyncMethods().routeChat(new StreamObserver<RouteNote>() {
            @Override
            public void onNext(RouteNote note) {
                System.out.println("========");
                System.out.printf("Got2 message \"{%s}\" at {%d}, {%d}\n", note.getMessage(), note.getLocation().getLatitude(), note.getLocation().getLongitude());
            }

            @Override
            public void onError(Throwable t) {
                finishFuture.setException(t);
            }

            @Override
            public void onCompleted() {
                finishFuture.set(null);
            }
        });

        try {
            RouteNote[] requests =
                    {
                            RouteNote.newBuilder().setMessage("First message").setLocation(Point.newBuilder().setLongitude(0).setLatitude(0).build()).build(),
                            RouteNote.newBuilder().setMessage("Second message").setLocation(Point.newBuilder().setLongitude(0).setLatitude(1).build()).build(),
                            RouteNote.newBuilder().setMessage("Third message").setLocation(Point.newBuilder().setLongitude(1).setLatitude(0).build()).build(),
                            RouteNote.newBuilder().setMessage("Fourth message").setLocation(Point.newBuilder().setLongitude(1).setLatitude(1).build()).build(),
//                            RouteNote.newBuilder().setMessage("Fifth message").setLocation(Point.newBuilder().setLongitude(1).setLatitude(1).build()).build(),
                    };

            for (RouteNote request : requests) {
                System.out.printf("Got message \"{%s}\" at {%d}, {%d}\n", request.getMessage(), request.getLocation().getLatitude(), request.getLocation().getLongitude());
                //发送请求
                requestObserver.onNext(request);
            }
            //发送完成
            requestObserver.onCompleted();
            //等待服务器完成
            finishFuture.get();
            System.out.println("Finished RouteChat");
        } catch (Exception t) {
            requestObserver.onError(t);
            System.out.println("RouteChat Failed");
        }

        return "";
    }
}
